perm filename F8[CLS,LSP] blob sn#871208 filedate 1989-03-17 generic text, type C, neo UTF8
COMMENT āŠ—   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	%Start Part 8 of 8 functi.tex
C00030 ENDMK
CāŠ—;
%Start Part 8 of 8 functi.tex
The system-supplied primary method on {\bf
update-instance-for-different-class} checks the validity of
initialization arguments and signals an error if an initialization
argument is supplied that is not declared as valid.  This method then
initializes slots with values according to the initialization
arguments, and initializes the newly added slots with values according
to their {\bf :initform} forms.  It does this by calling the generic
function {\bf shared-initialize} with the following arguments: the instance,
a list of names of the newly added slots, and the initialization
arguments it received.  Newly added slots are those local slots for which
no slot of the same name exists in the previous class.

Methods for {\bf update-instance-for-different-class} can be defined to
specify actions to be taken when an instance is updated.  If only {\bf
:after} methods for {\bf update-instance-for-different-class} are
defined, they will be run after the system-supplied primary method for
initialization and therefore will not interfere with the default
behavior of {\bf update-instance-for-different-class}.

\label Syntax:

\Defgen {update-instance-for-different-class} {previous current {\tt \&rest {\it initargs}}}

\label Method Signatures:

\Defmeth {update-instance-for-different-class} {\vtop{\hbox{({\it previous\/}
standard-object)}
\hbox{({\it current\/} standard-object)}
\hbox{{\tt \&rest {\it initargs}}}}}

\label Arguments:

The arguments to {\bf update-instance-for-different-class} are
computed by {\bf change-class}.  When {\bf change-class} is invoked on
an instance, a copy of that instance is made; {\bf change-class} then
destructively alters the original instance.  The first argument to
{\bf update-instance-for-different-class}, {\it previous\/}, is that
copy; it holds the old slot values temporarily.  This argument has
dynamic extent within {\bf change-class}; if it is referenced in any
way once {\bf update-instance-for-different-class} returns, the
results are undefined.  The second argument to {\bf
update-instance-for-different-class}, {\it current}, is the altered
original instance.

\vfill\eject
The intended use of {\it previous\/} is to extract old slot values by using
{\bf slot-value} or {\bf with-slots} or by invoking a reader generic
function, or to run other methods that were applicable to instances of
the original class.

The {\it initargs\/} argument consists of alternating initialization
argument names and values.

\label Values:

The value returned by {\bf update-instance-for-different-class} is
ignored by {\bf change-class}.

\label Examples:

See the example for the function {\bf change-class}.

\label Remarks:

Initialization arguments are declared as valid by using the {\bf
:initarg} option to {\bf defclass}, or by defining methods for {\bf
update-instance-for-different-class} or {\bf shared-initialize}.  The
keyword name of each keyword parameter specifier in the lambda-list of
any method defined on {\bf update-instance-for-different-class} or {\bf
shared-initialize} is declared as a valid initialization argument name
for all classes for which that method is applicable.

Methods on {\bf update-instance-for-different-class} can be defined to
initialize slots differently from {\bf change-class}.  The default
behavior of {\bf change-class} is described in ``Changing the Class of
an Instance.'' 


\label See Also:

``Changing the Class of an Instance''

``Rules for Initialization Arguments''

``Declaring the Validity of Initialization Arguments''

{\bf change-class

shared-initialize}

\endcom


\begincom{update-instance-for-redefined-class}\ftype{Standard Generic Function}

\label Purpose:

The generic function {\bf update-instance-for-redefined-class} is not
intended to be called by programmers. Programmers may
write methods for it.  The generic function {\bf
update-instance-for-redefined-class} is called by the mechanism
activated by {\bf make-instances-obsolete}.

The system-supplied primary method on {\bf
update-instance-for-different-class} checks the validity of
initialization arguments and signals an error if an initialization
argument is supplied that is not declared as valid.  This method then
initializes slots with values according to the initialization
arguments, and initializes the newly added slots with values according
to their {\bf :initform} forms.  It does this by calling the generic
function {\bf shared-initialize} with the following arguments: the instance,
a list of names of the newly added slots, and the initialization
arguments it received.  Newly added slots are those local slots for which
no slot of the same name exists in the old version of the class.

\label Syntax:

\Defgen {update-instance-for-redefined-class} {\vtop{\hbox{instance}
\hbox{added-slots discarded-slots}
\hbox{property-list}
\hbox{{\tt \&rest {\it initargs}}}}}

\label Method Signatures:

\Defmeth {update-instance-for-redefined-class} {\vtop{\hbox{({\it instance\/} standard-object)}
\hbox{\it added-slots discarded-slots}
\hbox{\it property-list}
\hbox{\&rest {\it initargs}}}}

\label Arguments:

When {\bf make-instances-obsolete} is invoked or when a class has been
redefined and an instance is being updated, a property list is created
that captures the slot names and values of all the discarded slots with
values in the original instance.  The structure of the instance is
transformed so that it conforms to the current class definition.  The
arguments to {\bf update-instance-for-redefined-class} are this
transformed instance, a list of the names of the new slots added to the
instance, a list of the names of the old slots discarded from the
instance, and the property list containing the slot names and values for
slots that were discarded and had values.  Included in this list of
discarded slots are slots that were local in the old class and are
shared in the new class.

The {\it initargs\/} argument consists of alternating initialization
argument names and values.

\label Values:

The value returned by {\bf update-instance-for-redefined-class} is ignored.

\label Remarks:

Initialization arguments are declared as valid by using the {\bf
:initarg} option to {\bf defclass}, or by defining methods for {\bf
update-instance-for-redefined-class} or {\bf shared-initialize}.  The
keyword name of each keyword parameter specifier in the lambda-list of
any method defined on {\bf update-instance-for-redefined-class} or {\bf
shared-initialize} is declared as a valid initialization argument name
for all classes for which that method is applicable.

\label Examples:

\screen!

(defclass position () ())

(defclass x-y-position (position)
    ((x :initform 0 :accessor position-x)
     (y :initform 0 :accessor position-y)))

;;; It turns out polar coordinates are used more than Cartesian 
;;; coordinates, so the representation is altered and some new
;;; accessor methods are added.

(defmethod update-instance-for-redefined-class :before
   ((pos x-y-position) added deleted plist &key)
  ;; Transform the x-y coordinates to polar coordinates
  ;; and store into the new slots.
  (let ((x (getf plist 'x))
        (y (getf plist 'y)))
    (setf (position-rho pos) (sqrt (+ (* x x) (* y y)))
          (position-theta pos) (atan y x))))

(defclass x-y-position (position)
    ((rho :initform 0 :accessor position-rho)
     (theta :initform 0 :accessor position-theta)))

;;; All instances of the old x-y-position class will be updated
;;; automatically.

;;; The new representation is given the look and feel of the old one.

(defmethod position-x ((pos x-y-position))  
   (with-slots (rho theta) pos (* rho (cos theta))))
\endscreen!
\vfill\eject
\screen!
(defmethod (setf position-x) (new-x (pos x-y-position))
   (with-slots (rho theta) pos
     (let ((y (position-y pos)))
       (setq rho (sqrt (+ (* new-x new-x) (* y y)))
             theta (atan y new-x))
       new-x)))

(defmethod position-y ((pos x-y-position))
   (with-slots (rho theta) pos (* rho (sin theta))))

(defmethod (setf position-y) (new-y (pos x-y-position))
   (with-slots (rho theta) pos
     (let ((x (position-x pos)))
       (setq rho (sqrt (+ (* x x) (* new-y new-y)))
             theta (atan new-y x))
       new-y)))

\endscreen!

\label See Also:

``Redefining Classes''

``Rules for Initialization Arguments''

``Declaring the Validity of Initialization Arguments''

{\bf make-instances-obsolete

shared-initialize
}

\endcom


\begincom{with-accessors}\ftype{Macro}

\label Purpose:

The macro {\bf with-accessors} creates a lexical environment in which
specified slots are lexically available through their accessors as if
they were variables.  The macro {\bf with-accessors} invokes the
appropriate accessors to access the specified slots.  Both {\bf setf}
and {\bf setq} can be used to set the value of the slot.

\label Syntax:  

\Defmac {with-accessors} {{\paren{\star{\curly{slot-entry\/}}}} instance-form\/  {\body} body}
{\it slot-entry\/}::$=$ {\paren{variable-name accessor-name\/}}

\label Values:

The result returned is that obtained by executing the forms specified
by the {\it body\/} argument.

\label Examples:

\screen!

(with-accessors ((x position-x)
                 (y position-y))
                p1
  (setq x y))

\endscreen!

\label Remarks:

A {\bf with-accessors} expression of the form:

$$\openup1\jot\vbox{\settabs\+\cr
\+{\tt (with-accessors} (${\hbox{{\it slot-entry}}}\sub 1%
\ldots{\hbox{{\it slot-entry}}}\sub n$) {\it instance\/}
${\hbox{{\it form}}}\sub 1%
\ldots{\hbox{{\it form}}}\sub k$)\cr}$$

\noindent expands into the equivalent of

$$\openup1\jot\vbox{\settabs\+\cr
\+{\tt (}&{\tt let ((}$in$ {\it instance}{\tt ))}\cr
\+&{\tt (symbol-macrolet (}${\hbox{{\it Q}}}\sub 1\ldots%
{\hbox{{\it Q}}}\sub n${\tt )} ${\hbox{{\it form}}}\sub 1%
\ldots{\hbox{{\it form}}}\sub k${\tt ))}\cr}$$

\noindent where ${\hbox{{\it Q}}}\sub i$ is 

$${\vbox{\hbox{{\tt (}${\hbox{{\it variable-name}}}\sub i$ %
{\tt (${\hbox{{\it accessor-name}}}\sub{i}\ in$))}}}}$$

\vfill\eject
\label See Also:

{\bf with-slots

 symbol-macrolet}

\endcom


\begincom{with-added-methods}\ftype{Special Form}

\label Purpose:

The {\bf with-added-methods} special form
produces new generic functions and establishes new
lexical function definition bindings.  Each generic function is created by
adding the set of methods specified by its method definitions to a copy of the
lexically visible generic function of the same name and its methods.  If
such a generic function does not already exist, a new generic function is
created; this generic function has lexical scope.

The special form {\bf with-added-methods} is used to define functions
whose names are meaningful only locally and to execute a series of
forms with these function definition bindings.


The names of functions defined by {\bf with-added-methods} have lexical
scope; they retain their local definitions only within the body of the
{\bf with-added-methods} construct.  Any references within the body of the
{\bf with-added-methods} construct to functions whose names are the same
as those defined within the {\bf with-added-methods} form are thus
references to the local functions instead of to any global functions
of the same names.  The scope of these generic function definition bindings
includes the method bodies themselves as well as the body of the {\bf
with-added-methods} construct.

\label Syntax:

\Defspec {with-added-methods} {
\vtop{\hbox{\lparen function-specifier lambda-list\/}
\hbox{\ $\lbrack\!\lbrack\downarrow\!$ option $\vert$ \star{method-description}\thinspace $\rbrack\!\rbrack$\thinspace\rparen}
\hbox{\star\form}}}
\Vskip 1pc!
{\it function-specifier\/}::$=$ \curly{{\it symbol\/} $\vert$ {\tt (setf {\it symbol\/})}}
\Vskip 1pc!
{\it option\/}::$=$ {\tt\vtop{\hbox{(:argument-precedence-order
\plus{\curly{parameter-name}}) $\vert$}
\hbox{(declare \plus{\curly{declaration\/}}) $\vert$}
\hbox{(:documentation {\it string\/}) $\vert$}
\hbox{(:method-combination {\it symbol\/} \star{\curly{arg\/}}) $\vert$}
\hbox{(:generic-function-class {\it class-name\/}) $\vert$}
\hbox{(:method-class {\it class-name\/})}}}
\Vskip 1pc!
{\it method-description\/}::$=$ {\tt (:method}
\vtop{\hbox{\it \star{\curly{method-qualifier\/}} specialized-lambda-list\/}
\hbox{\star{\curly{declaration\/ $\vert$ documentation\/}} \star{\curly{form\/}}{\tt )}}}

\vfill\eject
\label Arguments:

The {\it function-specifier\/}, {\it option}, {\it method-qualifier}, and {\it
specialized-lambda-list\/} arguments are the same as for {\bf defgeneric}.

The body of each method is enclosed in an implicit block.  If
{\it function-specifier\/} is a symbol, this block bears the same name as the
generic function.  If {\it function-specifier\/} is a list of the form {\tt
(setf {\it symbol\/})}, the name of the block is {\it symbol}.  

\label Values:

The result returned by {\bf with-added-methods} is the value or values
returned by the last form executed.  If no forms are specified, 
{\bf with-added-methods} returns {\bf nil}.

\label Remarks:

If a generic function with the given name already exists, the
lambda-list specified in the {\bf with-added-methods} form must be
congruent with the lambda-lists of all existing methods on that
function as well as with the lambda-lists of all methods defined by the
{\bf with-added-methods} form; otherwise an error is signaled.

If {\it function-specifier\/} specifies an existing generic function that has a
different value for any of the following {\it option\/} arguments, the
copy of that generic function is modified to have the new value: {\bf
:argument-precedence-order}, {\bf declare}, {\bf :documentation}, {\bf
:generic-function-class}, {\bf :method-combination}.

If {\it function-specifier\/} specifies an existing generic function that has a
different value for the {\bf :method-class} {\it option\/} argument,
that value is changed in the copy of that generic function, but any
methods copied from the existing generic function are not changed.

If a function of the given name already exists, that function is copied into
the default method for a generic function of the given name.  Note that
this behavior differs from that of {\bf defgeneric}.

If a macro or special form of the given name already exists, an error
is signaled.

If there is no existing generic function, the {\it option\/} arguments have
the same default values as the {\it option\/} arguments to {\bf defgeneric}.

%\vfill\eject
\label See Also:

{\bf generic-labels

generic-flet

defmethod

defgeneric

ensure-generic-function}

\endcom


\begincom{with-slots}\ftype{Macro}

\label Purpose:

The macro {\bf with-slots} creates a lexical context for referring to
specified slots as though they were variables.  Within such a context
the value of the slot can be specified by using its slot name, as if
it were a lexically bound variable.  Both {\bf setf} and {\bf setq}
can be used to set the value of the slot.

The macro {\bf with-slots} translates an appearance of the slot name as
a variable into a call to {\bf slot-value}.

\label Syntax:  

\Defmac {with-slots} {{\paren{\star{\curly{slot-entry\/}}}} instance-form\/  {\body} body}

{\it slot-entry\/}::$=$ {\it slot-name $\vert$ {\paren{variable-name slot-name\/}}}

\label Values:

The result returned is that obtained by executing the forms specified
by the {\it body\/} argument.

\label Examples:

\screen!

(with-slots (x y) position-1
  (sqrt (+ (* x x) (* y y))))


(with-slots ((x1 x) (y1 y)) position-1
  (with-slots ((x2 x) (y2 y)) position-2
     (psetf x1 x2
            y1 y2))))


  (with-slots (x y) position
    (setq x (1+ x)
          y (1+ y)))
\endscreen!

%\vfill\eject
\label Remarks:

A {\bf with-slots} expression of the form:

$$\openup1\jot\vbox{\settabs\+\cr
\+{\tt (with-slots} (${\hbox{{\it slot-entry}}}\sub 1%
\ldots{\hbox{{\it slot-entry}}}\sub n$) {\it instance\/}
${\hbox{{\it form}}}\sub 1%
\ldots{\hbox{{\it form}}}\sub k$)\cr}$$

\noindent expands into the equivalent of

$$\openup1\jot\vbox{\settabs\+\cr
\+{\tt (}&{\tt let ((}$in$ {\it instance}{\tt ))}\cr
\+&{\tt (symbol-macrolet (}${\hbox{{\it Q}}}\sub 1\ldots%
{\hbox{{\it Q}}}\sub n${\tt )} ${\hbox{{\it form}}}\sub 1%
\ldots{\hbox{{\it form}}}\sub k${\tt ))}\cr}$$

\noindent where ${\hbox{{\it Q}}}\sub i$ is 

$$\vbox{\hbox{{\tt (}${\hbox{{\it slot-entry}}}\sub i$
{\tt (slot-value }$in$ '${\hbox{{\it slot-entry}}}\sub i${\tt ))}}}$$

\noindent if ${\hbox{{\it slot-entry}}}\sub i$ is a symbol
and is

$${\vbox{\hbox{{\tt (}${\hbox{{\it variable-name}}}\sub i$ %
{\tt (slot-value }$in$ '${\hbox{{\it slot-name}}}\sub i${\tt ))}}}}$$

\noindent if ${\hbox{{\it slot-entry}}}\sub i$
is of the form 

$$\vbox{\hbox{{\tt (}${\hbox{{\it variable-name}}}\sub i$ %
${\hbox{{\it slot-name}}}\sub i${\tt )}}}$$

\label See Also:

{\bf with-accessors

symbol-macrolet}

\endcom

\endChapter
\bye


%End Part 8 of 8 functi.tex